Skip to content

Load images into ImageCache & Use non-async method in ImageCache #3898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

Jack251970
Copy link
Member

Load images into ImageCache

Load Constant.ImageIcon & Constant.LoadingImgIcon so that they can be freeze resources which can improve performance.

Use non-async method in ImageCache

Add non-async method in BinaryStorage so that ImageCache can use it to remove async methods.

And we can remove ImageLoader.WaitSaveAsync() to improve code quality

Test

  • Loading missing icon can work

Copy link

gitstream-cm bot commented Aug 13, 2025

🥷 Code experts: onesounds

Jack251970, onesounds have most 👩‍💻 activity in the files.
Jack251970 has most 🧠 knowledge in the files.

See details

Flow.Launcher.Infrastructure/Image/ImageLoader.cs

Activity based on git-commit:

Jack251970 onesounds
AUG
JUL
JUN
MAY
APR 123 additions & 48 deletions
MAR

Knowledge based on git-blame:
Jack251970: 26%

Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs

Activity based on git-commit:

Jack251970 onesounds
AUG
JUL
JUN
MAY
APR 91 additions & 37 deletions
MAR

Knowledge based on git-blame:
Jack251970: 59%

Flow.Launcher/MainWindow.xaml.cs

Activity based on git-commit:

Jack251970 onesounds
AUG
JUL 57 additions & 45 deletions
JUN 91 additions & 71 deletions 87 additions & 18 deletions
MAY 145 additions & 43 deletions 5 additions & 1 deletions
APR 69 additions & 45 deletions 5 additions & 1 deletions
MAR 1141 additions & 1076 deletions 327 additions & 141 deletions

Knowledge based on git-blame:
Jack251970: 64%

Flow.Launcher/PublicAPIInstance.cs

Activity based on git-commit:

Jack251970 onesounds
AUG
JUL 22 additions & 6 deletions
JUN 54 additions & 22 deletions
MAY 124 additions & 131 deletions 190 additions & 74 deletions
APR 165 additions & 61 deletions
MAR 21 additions & 19 deletions

Knowledge based on git-blame:
Jack251970: 54%

✨ Comment /gs review for LinearB AI review. Learn how to automate it here.

This comment has been minimized.

Copy link

gitstream-cm bot commented Aug 13, 2025

Be a legend 🏆 by adding a before and after screenshot of the changes you made, especially if they are around UI/UX.

@Jack251970 Jack251970 requested a review from Copilot August 13, 2025 06:11
@Jack251970 Jack251970 added this to the 2.0.0 milestone Aug 13, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR optimizes image loading performance by preloading constant images into ImageCache as frozen resources and removes async operations from ImageCache. The changes simplify the codebase by eliminating the need to wait for async image saving operations during app lifecycle events.

  • Preloads constant images (ImageIcon, LoadingImgIcon) into ImageCache as frozen resources
  • Replaces async image cache operations with synchronous ones using Lock instead of SemaphoreSlim
  • Removes ImageLoader.WaitSaveAsync() calls from app restart and shutdown sequences

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
PublicAPIInstance.cs Removes async from RestartApp() and replaces async image saving with synchronous Save()
MainWindow.xaml.cs Removes ImageLoader using statement and WaitSaveAsync() call from shutdown
BinaryStorage.cs Adds synchronous TryLoad() and Save() methods, improves error handling
ImageLoader.cs Replaces async operations with sync, preloads constant images, uses Lock instead of SemaphoreSlim

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@Jack251970 Jack251970 added enhancement New feature or request Code Quality labels Aug 13, 2025
Copy link
Contributor

coderabbitai bot commented Aug 13, 2025

📝 Walkthrough

Walkthrough

Centralizes image sources in ImageCache, reworks ImageLoader initialization and concurrency to use synchronous storage load/save with locks, expands preloaded icons, and removes async wait/save from shutdown/restart. Adds synchronous load/save/clear helpers to BinaryStorage and updates shutdown/restart call sites accordingly.

Changes

Cohort / File(s) Summary
Image loading refactor & concurrency
Flow.Launcher.Infrastructure/Image/ImageLoader.cs
Public icon properties now resolve from ImageCache[...]; InitializeAsync restructured to load storage synchronously, clear storage, init ImageCache with usage, and preload additional icons; replaced SemaphoreSlim/async save with synchronous Save() under a lock; removed WaitSaveAsync; standardized missing-image handling.
Storage API extensions
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
Added TryLoad(T), Save(), Save(T), and ClearData(); refactored sync/async deserialize helpers with default fallbacks and zero-length/missing-file handling; Save() delegates to Save(Data.NonNull()).
Shutdown / restart call sites
Flow.Launcher/MainWindow.xaml.cs, Flow.Launcher/PublicAPIInstance.cs
Removed awaiting of image-cache save on closing; RestartApp() changed from async void to synchronous void; settings save now calls ImageLoader.Save() synchronously and no longer waits for async image saves.

Sequence Diagram(s)

sequenceDiagram
  participant App as App Startup
  participant Img as ImageLoader
  participant Store as BinaryStorage
  participant Cache as ImageCache

  App->>Img: InitializeAsync()
  activate Img
  Img->>Store: TryLoad(defaultUsage)
  Store-->>Img: usageData
  Img->>Store: ClearData()
  Img->>Cache: Initialize(usageData)
  Img->>Cache: Preload(DefaultIcon, ImageIcon, MissingImgIcon, LoadingImgIcon)
  Img-->>App: Initialized
  deactivate Img
Loading
sequenceDiagram
  participant UI as UI/Shutdown/Restart
  participant API as PublicAPIInstance
  participant Img as ImageLoader
  participant Store as BinaryStorage

  UI->>API: SaveAppAllSettings()
  API->>Img: Save()  (synchronous)
  Img->>Store: Save(data)
  Store-->>Img: Saved
  API-->>UI: Done
  UI->>API: RestartApp()
  API-->>UI: Restart (no await on image save)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • onesounds
  • jjw24
  • taooceros

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e06e6e2 and 3727bff.

📒 Files selected for processing (1)
  • Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: gitStream.cm
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch storage_api_method

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs (1)

15-15: Fix typo in documentation comment.

There's a typo in the XML documentation comment.

-    /// Stroage object using binary data
+    /// Storage object using binary data
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b08c96 and e06e6e2.

📒 Files selected for processing (4)
  • Flow.Launcher.Infrastructure/Image/ImageLoader.cs (5 hunks)
  • Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs (3 hunks)
  • Flow.Launcher/MainWindow.xaml.cs (0 hunks)
  • Flow.Launcher/PublicAPIInstance.cs (2 hunks)
💤 Files with no reviewable changes (1)
  • Flow.Launcher/MainWindow.xaml.cs
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3897
File: Flow.Launcher/ViewModel/PluginViewModel.cs:46-51
Timestamp: 2025-08-13T06:12:43.361Z
Learning: In Flow Launcher's PluginViewModel.cs, the LoadIconAsync method does not require additional try-catch error handling according to maintainer Jack251970, as the existing error handling approach is considered sufficient for the image loading operations.
📚 Learning: 2025-02-28T07:47:24.148Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3279
File: Flow.Launcher/Helper/WallpaperPathRetrieval.cs:44-46
Timestamp: 2025-02-28T07:47:24.148Z
Learning: In Flow.Launcher's WallpaperPathRetrieval class, using a `using` statement with MemoryStream when loading images with BitmapImage does not work properly, even when using BitmapCacheOption.OnLoad. The stream needs to remain open while the bitmap is in use.

Applied to files:

  • Flow.Launcher.Infrastructure/Image/ImageLoader.cs
🧬 Code Graph Analysis (3)
Flow.Launcher/PublicAPIInstance.cs (3)
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs (1)
  • RestartApp (34-34)
Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs (1)
  • RestartApp (27-30)
Flow.Launcher.Infrastructure/Image/ImageLoader.cs (2)
  • ImageLoader (17-411)
  • Save (72-85)
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs (6)
Flow.Launcher.Infrastructure/Helper.cs (1)
  • T (12-22)
Flow.Launcher.Infrastructure/Logger/Log.cs (5)
  • Log (13-168)
  • Log (19-64)
  • Error (140-143)
  • Info (159-162)
  • Exception (97-107)
Flow.Launcher.Infrastructure/Image/ImageLoader.cs (1)
  • Save (72-85)
Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs (1)
  • Save (24-34)
Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs (1)
  • Save (22-32)
Flow.Launcher.Plugin/Interfaces/ISavable.cs (1)
  • Save (19-19)
Flow.Launcher.Infrastructure/Image/ImageLoader.cs (3)
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs (6)
  • BinaryStorage (21-169)
  • BinaryStorage (34-36)
  • BinaryStorage (38-44)
  • ClearData (165-168)
  • Save (135-138)
  • Save (140-147)
Flow.Launcher.Infrastructure/Image/ImageCache.cs (1)
  • ImageCache (10-79)
Flow.Launcher.Infrastructure/Constant.cs (1)
  • Constant (7-59)
🪛 GitHub Actions: Check Spelling
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs

[warning] 15-16: Unrecognized spelling: 'Stroage'.

Flow.Launcher.Infrastructure/Image/ImageLoader.cs

[warning] 406-406: Unrecognized spelling: 'Pbgra'.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: gitStream workflow automation
  • GitHub Check: gitStream.cm
  • GitHub Check: build
🔇 Additional comments (14)
Flow.Launcher/PublicAPIInstance.cs (2)

77-90: LGTM! Synchronous restart flow is appropriate here.

The removal of async from RestartApp() is correct since the method performs synchronous operations and calls Environment.Exit(0) via UpdateManager.RestartApp(). The synchronous SaveAppAllSettings() call ensures all settings are persisted before the application terminates.


108-117: LGTM! Proper synchronization of save operations.

The addition of ImageLoader.Save() ensures image cache is persisted along with other application settings. The lock properly synchronizes all save operations to prevent concurrent modifications.

Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs (6)

56-79: LGTM! Well-structured synchronous load method with proper error handling.

The TryLoad method implementation correctly handles all edge cases:

  • Returns cached data if already loaded
  • Handles zero-length files with appropriate logging and recovery
  • Creates default data for missing files
  • Properly deserializes existing files with error recovery

81-93: LGTM! Robust deserialization with proper error recovery.

The private Deserialize method properly handles deserialization errors by logging the exception and returning the default data as a fallback, ensuring the application continues to function even with corrupted cache files.


121-133: LGTM! Consistent async deserialization implementation.

The async deserialization helper maintains consistency with the synchronous version, properly handling errors and returning default data as fallback.


135-138: LGTM! Proper delegation to parameterized Save method.

The parameterless Save() method correctly delegates to Save(T data) using NonNull() extension to ensure data is not null.


140-147: LGTM! Clean synchronous save implementation.

The new Save(T data) method provides a clean synchronous API that validates the directory exists and serializes the data efficiently using MemoryPack.


163-168: LGTM! Useful utility for clearing in-memory cache.

The ClearData() method provides a clean way to reset the in-memory cache, which is particularly useful for the ImageCache implementation that needs to manage memory efficiently.

Flow.Launcher.Infrastructure/Image/ImageLoader.cs (6)

22-22: LGTM! Appropriate switch to Lock for synchronous operations.

The change from SemaphoreSlim to Lock is appropriate since all storage operations are now synchronous. The Lock type provides better performance for synchronous scenarios.


27-29: LGTM! Clever centralization of image sources in ImageCache.

Moving the image sources (Image, MissingImage, LoadingImage) to be computed from ImageCache ensures these resources are properly frozen and managed centrally, improving performance and consistency.


39-57: LGTM! Well-structured initialization with proper preloading.

The initialization properly:

  1. Sets up storage in a background task
  2. Loads existing cache entries
  3. Clears storage data to free memory
  4. Initializes ImageCache
  5. Preloads essential icons as frozen resources

This approach ensures optimal memory usage and performance.


72-85: LGTM! Clean synchronous save implementation with proper error handling.

The synchronous Save() method properly:

  • Acquires the lock to ensure thread safety
  • Saves the current cache entries using LINQ to extract keys
  • Handles exceptions gracefully with logging

87-93: LGTM! Consistent synchronous storage loading.

The change from async to synchronous loading aligns with the overall refactoring and properly uses the lock for thread safety.


125-127: LGTM! Consistent use of MissingImage property.

All references to missing image icons now consistently use the MissingImage property instead of direct access, ensuring centralized management through ImageCache.

Also applies to: 166-168, 265-266

Copy link

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

❌ Errors and Warnings Count
❌ forbidden-pattern 2
⚠️ non-alpha-in-dictionary 2

See ❌ Event descriptions for more information.

Forbidden patterns 🙅 (1)

In order to address this, you could change the content to not match the forbidden patterns (comments before forbidden patterns may help explain why they're forbidden), add patterns for acceptable instances, or adjust the forbidden patterns themselves.

These forbidden patterns matched content:

s.b. workaround(s)

\bwork[- ]arounds?\b
If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant